import datetime, json
import platform
import uuid
from typing import List
from fastapi import APIRouter, WebSocket, Form, UploadFile, File
from src.core.session import *
from src.entity.models import OutMindMap, CreateMindMap, UpdateMindMap, MindMap, BasicModel
from src.common.response import success_response, fail_response
from src.core.logconfig import log
from config import SETTINGS
import zipfile
import json
from io import BytesIO
from src.utils.tools import get_cur_time

mind = APIRouter()


async def query_mind_info(nd):
    n,s,f = 0,0,0
    if nd is not None:
        nd = json.loads(nd.content)['nodeData']
        # 对子节点进行迭代
        def query_node_c(node: list):
            nonlocal n, s, f
            for i in node:
                # 遍历字典，如果没有children字典，直接计数；如果有则判断是否有子节点
                # 末位节点有两种情况：1. 没有子节点字段；2. 有children字段，但数据为空；
                if 'children' not in i:
                    # 计算当前节点的状态，查找节点中tag或icon中的数据
                    if 'icons' in i:
                        if '✅' in i['icons']:
                            s += 1
                        if '❌' in i['icons']:
                            f += 1
                    n += 1
                    continue
                if 'children' in i:
                    if  len(i['children'])>0:
                        query_node_c(i['children'])
                    else:
                        if 'icons' in i:
                            if '✅' in i['icons']:
                                s += 1
                            if '❌' in i['icons']:
                                f += 1
                        n += 1

        # 对map数据进行遍历，计算节点总数
        for i in nd:
            # 遍历节点，如果当前节点无子节点，则认定为未节点，对节点数更新，否则将进行迭代
            if "children" in nd and i == 'children':
                if len(nd[i]) > 0:
                    query_node_c(nd[i])
                else:
                    if 'icons' in i:
                        if '✅' in i['icons']:
                            s += 1
                        if '❌' in i['icons']:
                            f += 1
                    n += 1
    return { "count": n, "s": s, "f": f}


# 新建xmind
@mind.post("/create", response_model=OutMindMap)
async def create_mindmap(mindmap: CreateMindMap):
    try:
        # 增加对节点数据的扫描
        res_s = (await query_mind_info(mindmap))
        mindmap.progress_t = f"({res_s['s']}/{res_s['count']})={ int(res_s['s']/res_s['count'] * 100) }%"
        # progress_s = ''
        mindmap.create_time = get_cur_time()
        mindmap.update_time = get_cur_time()
        return success_response(SQLCON.db_create(entity=MindMap, create=mindmap))
    except Exception as e:
        raise success_response(d="", m=e)

# 获取xmind列表
@mind.post("/getMindList", response_model=List[OutMindMap])
async def read_mindmap(order: str = Form(default='update_time')):
    sql = select(MindMap.id, MindMap.create_time,MindMap.update_time, MindMap.title, MindMap.format, MindMap.progress_s, MindMap.progress_t, MindMap.create_by, MindMap.update_by, MindMap.is_deleted)
    if order == 'update_time':
        sql = sql.order_by(MindMap.update_time.desc())
    else:
        sql = sql.order_by(MindMap.create_time.desc())
    
    # sql = select(MindMap).order_by(MindMap.update_time.desc())   # 按更新时间降序排序，查询所有
    mmap = SQLCON.db_query_filter(MindMap, sql=sql)    
    if mmap == []:
        fail_response(mmap)
    return success_response([OutMindMap(**i._asdict()) for i in mmap])

# 通过id获取xmind
@mind.post("/getMindById", response_model=OutMindMap)
async def query_mindmap(mindmap: BasicModel):
    mmap = SQLCON.db_query_by_id(MindMap, mindmap.id)
    if mmap is None:
        return success_response("未查询到数据")
    # log.logger.info(f"mindmap data: {mmap.content}")
    return success_response(mmap)

@mind.post("/update")
async def update_mindmap(mindmap: UpdateMindMap):
    mmap = SQLCON.db_query_by_id(MindMap, mindmap.id)
    if mmap is None:
        return success_response(mmap)
    mindmap.update_time = get_cur_time()
    # 获取mind节点信息
    res_s = (await query_mind_info(mmap))
    mindmap.progress_t = f"({res_s['s']}/{res_s['count']})={ int(res_s['s']/res_s['count'] * 100) }%"
    res = SQLCON.db_update(MindMap, mindmap)
    return success_response(res)

@mind.post("/delete")
async def del_mindmap(mindmap: BasicModel):
    mmap = SQLCON.db_query_by_id(MindMap, mindmap.id)
    if mmap is None:
        return success_response("未查询到数据")
    # 更新数据为删除状态
    return success_response(SQLCON.db_del_by_id(MindMap, mindmap.id))


# 读写xmind文件，并转换为dict
@mind.post("/upload")
async def read_file(file: UploadFile = File(...)):
    # 转换为ME格式
    data = convert_xmind_content(read_xmind_file(file))
    model = CreateMindMap(title=data['nodeData']['topic'], content=json.dumps(data, ensure_ascii=False))
    model.create_time = get_cur_time()
    log.logger.debug(f"upload file to model: {model}")
    return success_response(SQLCON.db_create(entity=MindMap, create=model))
    
def read_xmind_file(file):
    try:
        # 将 UploadFile 转换为字节流
        with zipfile.ZipFile(BytesIO(file.file.read())) as zip_ref:
            # 查找 content.json（不同版本的 XMind 可能路径不同）
            content_path = None
            for name in zip_ref.namelist():
                if name.endswith('content.json') or name.endswith('contents/content.json'):
                    content_path = name
                    break
            if not content_path:
                raise ValueError("XMind 文件中未找到 content.json")
            # 读取并解析 JSON
            with zip_ref.open(content_path) as f:
                content = json.load(f)
                return content
    
    except zipfile.BadZipFile:
        raise "无效的 ZIP 文件（可能不是 XMind 文件）"
    except json.JSONDecodeError:
        raise "content.json 解析失败"
    except Exception as e:
        raise f"解析失败: {str(e)}"


def convert_xmind_content(xc: dict) -> dict:
    """
    将XMind内容转换为MindElixir格式

    参数:
        xc: dict - XMind解析出的内容字典

    返回:
        dict - MindElixir格式的字典
    """
    # 处理新版XMind Zen格式
    if 'canvas' in xc:
        root_topic = xc['canvas']['rootTopic']
    # 处理旧版XMind 8格式
    elif isinstance(xc, list) and len(xc) > 0 and 'rootTopic' in xc[0]:
        root_topic = xc[0]['rootTopic']
    else:
        raise ValueError("无法识别的XMind格式")
    
    # 转换根节点
    mindelixir_data = {
        "nodeData": convert_topic(root_topic),
        "theme": {
            "name": 'latte',
            "palette": []
        }
    }
    
    return mindelixir_data


def convert_topic(topic: dict) -> dict:
    """
    递归转换XMind主题节点为MindElixir节点

    参数:
        topic: Dict - XMind主题节点

    返回:
        Dict - MindElixir节点
    """
    if not topic:
        return {"topic": "空节点", "id": str(uuid.uuid4())}
    
    node = {
        "id": topic.get('id', str(uuid.uuid4())),
        "topic": topic.get('title', '未命名节点'),
        "expanded": True
    }
    
    # 处理子节点
    if 'children' in topic and 'attached' in topic['children']:
        node['children'] = [ convert_topic(child) for child in topic['children']['attached'] ]
    
    # 处理标签
    if 'labels' in topic:
        node['tags'] = list(topic['labels'])
    
    # 处理备注
    if 'notes' in topic and 'plain' in topic['notes']:
        node['note'] = topic['notes']['plain']['content']
    
    # 处理样式
    if 'style' in topic:
        style = {}
        if 'font-size' in topic['style']:
            style['fontSize'] = topic['style']['font-size']
        if 'color' in topic['style']:
            style['color'] = topic['style']['color']
        if 'background-color' in topic['style']:
            style['background'] = topic['style']['background-color']
        if style:
            node['style'] = style
    return node
